package yiling

import (
	"context"
	"crypto/md5"
	"fmt"
	"hash"
	"sync"

	"github.com/go-pay/gopay"
	"github.com/go-pay/gopay/pkg/xhttp"
	"github.com/go-pay/xlog"
)

type Client struct {
	merchantNo string // 支付系统：商户号
	key        string
	version    string
	hc         *xhttp.Client
	mu         sync.Mutex
	md5Hash    hash.Hash
}

// NewClient 初始化扫呗客户端
// merchantNo  string // 支付系统：商户号
// key         string // 商户系统令牌
func NewClient(merchantNo, key string) (*Client, error) {
	return &Client{
		key:        key,
		merchantNo: merchantNo,
		hc:         xhttp.NewClient(),
		md5Hash:    md5.New(),
		version:    "3.0",
	}, nil
}

// pubParamsHandle 公共参数处理
func (c *Client) pubParamsHandle(bm gopay.BodyMap) gopay.BodyMap {
	if ver := bm.GetString("version"); ver == gopay.NULL {
		bm.Set("version", c.version)
	}

	if v := bm.GetString("merchantNum"); v == gopay.NULL {
		bm.Set("merchantNum", c.merchantNo)
	}
	sign := c.getRsaSign(bm)

	bm.Set("sign", sign)

	return bm
}

// doAllocatePost 发起请求
func (c *Client) postBase(ctx context.Context, url, path string, bm gopay.BodyMap) (bs []byte, err error) {

	xlog.Debugf("saobeiParam:%+v", bm.JsonBody())
	res, bs, err := c.hc.Req(xhttp.TypeJSON).Post(url + path).SendBodyMap(bm).EndBytes(ctx)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
	}
	return bs, nil
}

// doPost 发起请求
func (c *Client) doPost(ctx context.Context, bm gopay.BodyMap) (bs []byte, err error) {
	param := c.pubParamsHandle(bm)
	if err != nil {
		return nil, err
	}

	xlog.Debugf("saobeiParam:%+v", param.JsonBody())

	res, bs, err := c.hc.Req(xhttp.TypeJSON).Post(baseUrl).SendBodyMap(param).EndBytes(ctx)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
	}
	return bs, nil
}
